#define _CRT_SECURE_NO_WARNINGS
#pragma execution_character_set("utf-8")

#include <stdio.h> 

#include <string.h> 

#include <malloc.h>

#include "struct.h"

int rec_tmp = 0;

void Init() {

    strcpy(User, "null");  // 初始化用户名

    View_Level = -2;   // 初始化应用权限

    read_student();

    read_account();

    Loop = 1;

    return;

}

void input_time(time* Cur, int year, int month, int day) { // 用函数输入 年 月 日

    (*Cur).year = year;

    (*Cur).month = month;

    (*Cur).day = day;

    return;

}

void read_student() {  // student文件 转 student结构体

    FILE* tmp; // 判断文件是否存在

    int error1;

    error1 = fopen_s(&tmp, "data\\student.txt", "r"); // 确认学生文件是否能打开

    if (error1 == 1) { //学生文件不存在

        printf("错误 未找到学生文件\n");

        Loop = 0;

        return;

    }

    else fclose(tmp); //判断结束

    FILE* fp;

    fp = fopen("data\\student.txt", "r"); //只读方式打开文件

    pH_student = (student*)malloc(sizeof(student)); //初始化头尾指针

    pT_student = pH_student;

    rec_tmp = fscanf(fp, "%s\n", pT_student->id); // 读入无效值

    while (!feof(fp)) { // 建链表

        student* pT_next;

        pT_next = (student*)malloc(sizeof(student));

        pT_student->next = pT_next;

        pT_student = pT_next;

        rec_tmp = fscanf(fp, "%s %s %s %d %d \n", pT_student->id, pT_student->name, pT_student->sexual, &(pT_student->major), &(pT_student->session)); // 从文件读入该节点内容

        pT_student->pH_medal = NULL; // 把学生的各项成绩指针初始化

        pT_student->pH_paper = NULL;

        pT_student->pH_project = NULL;

        pT_student->pH_subject = NULL;

        pT_student->pT_medal = NULL;

        pT_student->pT_paper = NULL;

        pT_student->pT_project = NULL;

        pT_student->pT_subject = NULL; // 指针初始化结束

    }

    pT_student->next = NULL; // 结构体末尾指向空

    fclose(fp); //建好结构体后直接关闭文件

    return;

}

void write_student() { // student 结构体 写入 文件

    if (pH_student != NULL) { // 避免对空的头节点进行释放

        FILE* fp;

        fp = fopen("data\\student.txt", "w"); //只写（会删除原内容）

        student* p_next = pH_student->next; 

        fprintf(fp, "学生\n");

        free(pH_student);  // 单独释放头指针

        while (p_next != NULL) {

            fprintf(fp, "%s %s %s %d %d \n", p_next->id, p_next->name, p_next->sexual, p_next->major, p_next->session);

            student* p_free = p_next;

            p_next = p_next->next; //指向下一个位置

            write_medal(p_free); // 写入他的所有成绩文件

            write_paper(p_free);

            write_project(p_free);

            write_subject(p_free);

            free(p_free); // 释放相应空间

        }

        pH_student = NULL;

        pT_student = NULL; // 初始化尾指针

        fclose(fp);

    }

    return;

}

void create_student() { // 在末尾新建一个已经初始化的学生节点

    student* q;

    q = (student*)malloc(sizeof(student));

    strcpy(q->id, "null"); // 初始化开始

    strcpy(q->name, "null");

    strcpy(q->sexual, "null");

    q->major = -2;

    q->session = -2;

    q->pH_subject = NULL;

    q->pT_subject = NULL;

    q->pH_medal = NULL;

    q->pT_medal = NULL;

    q->pH_project = NULL;

    q->pT_project = NULL;

    q->pH_paper = NULL;

    q->pT_paper = NULL;

    q->next = NULL;  // 初始化结束

    pT_student->next = q;

    pT_student = q; // 更新尾指针

    return;

}

void delete_student(student* p_last) { // 删除 当前节点的下一个节点

    student* p_cur = p_last->next; // p_cur 为 p_last 的 下一个节点

    if (p_cur == NULL) return;

    p_last->next = p_cur->next; // 更新 p_last 的 下一个

    char file_subject[40]; // 删除对应学生的成绩文件

    char file_project[40];

    char file_medal[40];

    char file_paper[40];

    strcpy(file_subject, "");

    strcpy(file_project, "");

    strcpy(file_medal, "");

    strcpy(file_paper, "");

    strcpy(file_subject, "data\\subject");

    strcpy(file_project, "data\\project");

    strcpy(file_medal, "data\\medal");

    strcpy(file_paper, "data\\paper");

    strcat(file_subject, p_cur->id);

    strcat(file_project, p_cur->id);

    strcat(file_medal, p_cur->id);

    strcat(file_paper, p_cur->id);

    strcat(file_subject, ".txt");

    strcat(file_project, ".txt");

    strcat(file_medal, ".txt");

    strcat(file_paper, ".txt");

    remove(file_subject); // 如果一个学生的“节点被删除”，那么要删除对应“成绩的文件”

    remove(file_project);

    remove(file_medal);

    remove(file_paper);

    write_subject(p_cur); // 要把这个学生的成绩结构体的空间释放

    write_project(p_cur);

    write_medal(p_cur);

    write_paper(p_cur);

    free(p_cur); // 释放被删除的节点的空间(必须放最后)

    return;

}

void read_account() {  // account 文件 转 结构体

    FILE* tmp2; //判读文件是否存在

    int error1;

    error1 = fopen_s(&tmp2, "data\\account.txt", "r"); // 确认账户文件是否能打开

    if (error1 == 1) { //账户文件不存在

        printf("错误 未找到账户文件\n");

        Loop = 0;

        return;

    }

    else fclose(tmp2); //判断结束

    FILE* fp;

    fp = fopen("data\\account.txt", "r"); //只读方式打开文件

    pH_account = (account*)malloc(sizeof(account)); //初始化头尾指针

    pT_account = pH_account;

    rec_tmp = fscanf(fp, "%s\n", pT_account->user); // 读入无效值

    while (!feof(fp)) { // 建链表

        account* pT_next;

        pT_next = (account*)malloc(sizeof(account));

        pT_account->next = pT_next;

        pT_account = pT_next; // 维持尾指针指向末尾

        rec_tmp = fscanf(fp, "%s %s %d \n", pT_account->user, pT_account->password, &(pT_account->view_level)); // 从文件读入该节点内容

    }

    pT_account->next = NULL; // 结构体末尾指向空

    fclose(fp); //建好结构体后直接关闭文件

    return;

}

void write_account() { // account 结构体 写入 文件

    if (pH_account != NULL) { // 避免对空的头节点进行释放

        FILE* fp;

        fp = fopen("data\\account.txt", "w"); //只写（删除原内容）

        account* p_next = pH_account->next; //标注已写入数据的空间方便释放

        fprintf(fp,"账户\n"); //写入无效值

        free(pH_account); //单独释放头指针

        while (p_next != NULL) {

            fprintf(fp, "%s %s %d \n", p_next->user, p_next->password, p_next->view_level);

            account* p_free = p_next; // 释放相应空间 

            p_next = p_next->next; //指向下一个位置

            free(p_free);

        }

        fclose(fp);

        pH_account = NULL;

        pT_account = NULL;

    }

    return;

}

void create_account() { // 在末尾新建一个已经初始化的account节点

    account* q;

    q = (account*)malloc(sizeof(account));

    strcpy(q->user, "null"); // 初始化开始

    strcpy(q->password, "null");

    q->view_level = -2;

    q->next = NULL; // 初始化结束

    pT_account->next = q;

    pT_account = q; // 更新尾指针

    return;

}

void delete_account(account* p_last) { // 删除 p_last 的下一个节点 p_cur

    account* p_cur;

    p_cur = p_last->next;

    if (p_cur == NULL) return;

    p_last->next = p_cur->next;

    free(p_cur);

    return;

}

void read_subject(student* p) {  // 文件 读取 subject 结构体

    if (p->pH_subject != NULL) return;

    char fname[40];

    strcpy(fname, "data\\subject\\");

    strcat(fname, p->id);

    strcat(fname, ".txt");

    FILE* fp;

    fp = fopen(fname, "r"); //只读方式打开文件

    p->pH_subject = (subject*)malloc(sizeof(subject)); //初始化头尾指针

    p->pT_subject = p->pH_subject;

    if (fp == NULL) { //如果文件为空，则建立一个无意义的头节点

        strcpy(p->pT_subject->name, "科目");

    }

    else {

        rec_tmp = fscanf(fp, "%s\n",p->pT_subject->name); // 读入无效值

        while (!feof(fp)) { //建表

            subject* pT_next; //next指针下一个预留空间

            pT_next = (subject*)malloc(sizeof(subject));

            (p->pT_subject)->next = pT_next;

            p->pT_subject = pT_next;

            rec_tmp = fscanf(fp, "%s %s %f %f %f %d \n", p->pT_subject->node, p->pT_subject->name, &((p->pT_subject)->cavlue), &((p->pT_subject)->grade), &((p->pT_subject)->gpa), &((p->pT_subject)->type)); // 读入该节点内容

        }

        fclose(fp); //建好结构体后直接关闭文件

    }

    (p->pT_subject)->next = NULL; // 结构体末尾指向空

}

void write_subject(student* p) { // subject 结构体 写入 文件

    if (p->pH_subject != NULL) { // 避免对空的头节点进行释放

        char fname[40];

        strcpy(fname, "data\\subject\\");

        strcat(fname, p->id);

        strcat(fname, ".txt");

        FILE* fp;

        fp = fopen(fname, "w"); //只写（删除原内容）

        subject* p_next = (p->pH_subject)->next;

        fprintf(fp, "科目\n"); // 写入无效值

        free(p->pH_subject);

        while (p_next != NULL) {

            fprintf(fp, "%s %s %f %f %f %d \n", p_next->node, p_next->name, p_next->cavlue, p_next->grade, p_next->gpa, p_next->type);

            subject* p_free = p_next; // 释放相应空间 

            p_next = p_next->next; //指向下一个位置

            free(p_free);

        }

        fclose(fp);

        p->pH_subject = NULL;

        p->pT_subject = NULL;

    }

    return;

}

void create_subject(student* p) { // 在末尾新建一个已经初始化的subject节点

    subject* tmp;

    tmp = (subject*)malloc(sizeof(subject));

    // 初始化开始

    strcpy(tmp->name, "null");

    strcpy(tmp->node, "null");

    tmp->cavlue = -2;

    tmp->grade = -2;

    tmp->gpa = -2;

    tmp->type = -2;

    tmp->next = NULL;

    // 初始化结束

    p->pT_subject->next = tmp;

    p->pT_subject = tmp; // 更新尾指针

    return;

}

void delete_subject(subject* p_last) { // 删除 p_last 的下一个节点 p_cur

    subject* p_cur;

    p_cur = p_last->next;

    if (p_cur == NULL) return;

    p_last->next = p_cur->next;

    free(p_cur);

    return;

}

void read_project(student* p) {  // 文件 读取 project 结构体

    if (p->pH_project != NULL) return;

    char fname[40];

    strcpy(fname, "data\\project\\");

    strcat(fname, p->id);

    strcat(fname, ".txt");

    FILE* fp;

    fp = fopen(fname, "r"); //只读方式打开文件

    p->pH_project = (project*)malloc(sizeof(project)); //初始化头尾指针

    p->pT_project = p->pH_project;

    if (fp == NULL) { //如果文件为空，对文件进行初始化（添加一个无效值头文件）

        strcpy(p->pT_project->name, "项目");

    }

    else {

        // 读入无效值

        rec_tmp = fscanf(fp, "%s\n", (p->pT_project)->name);

        // 读入无效值结束

        while (!feof(fp)) { //建表

            project* pT_next;

            pT_next = (project*)malloc(sizeof(project));

            (p->pT_project)->next = pT_next;

            p->pT_project = pT_next;

            // 读入文件中一个项目的所有信息

            rec_tmp = fscanf(fp, "%s %s ", (p->pT_project)->node ,(p->pT_project)->name);

            for (int i = 0; i < 20; i++) {

                rec_tmp = fscanf(fp, "%s ", (p->pT_project)->member[i]);

            }

            rec_tmp = fscanf(fp, "%s ", (p->pT_project)->teacher);

            rec_tmp = fscanf(fp, "%d %d %d %d %d %d %f \n", &((p->pT_project)->start).year, &((p->pT_project)->start).month, &((p->pT_project)->start).day, &((p->pT_project)->finish).year, &((p->pT_project)->finish).month, &((p->pT_project)->finish).day, &(p->pT_project)->level);

            // 读入结束

        }

        fclose(fp); //建好结构体后直接关闭文件

    }

    (p->pT_project)->next = NULL; // 结构体末尾指向空

    return;

}

void write_project(student* p) { // subject 结构体 写入 文件

    if (p->pH_project != NULL) { // 避免对空的头节点进行释放

        char fname[40];

        strcpy(fname, "data\\project\\");

        strcat(fname, p->id);

        strcat(fname, ".txt");

        FILE* fp;

        fp = fopen(fname, "w"); //只写（删除原内容）

        project* p_next; //标注已写入数据的空间方便释放

        p_next = NULL;

        fprintf(fp, "项目\n");

        p_next = (p->pH_project)->next;

        free(p->pH_project);

        while (p_next != NULL) {

            // 读入文件中一个项目的所有信息

            fprintf(fp, "%s %s ", p_next->node, p_next->name );

            for (int i = 0; i < 20; i++) {

                fprintf(fp, "%s ", p_next->member[i]);

            }

            fprintf(fp, "%s ", p_next->teacher ); // 读入无效值

            fprintf(fp, "%d %d %d %d %d %d %f \n", (p_next->start).year, (p_next->start).month, (p_next->start).day, (p_next->finish).year, (p_next->finish).month, (p_next->finish).day, p_next->level);

            // 读入结束

            project* p_free = p_next; // 释放相应空间 

            p_next = p_next->next; //指向下一个位置

            free(p_free);

        }

        p->pH_project = NULL;

        p->pT_project = NULL;

        fclose(fp);

    }

}

void create_project(student* p) { // 在末尾新建一个已经初始化的subject节点

    project* tmp;

    tmp = (project*)malloc(sizeof(project));

    // 初始化开始

    strcpy(tmp->name, "项目名称");

    for (int i = 0; i < 20; i++) { strcpy(tmp->member[i], "null"); }

    strcpy(tmp->teacher, "null");

    strcpy(tmp->node, "null");

    input_time(&(tmp->start), -2, -2, -2);

    input_time(&(tmp->finish), -2, -2, -2);

    tmp->level = 0;

    tmp->next = NULL;

    // 初始化结束

    (p->pT_project)->next = tmp;

    p->pT_project = tmp; // 更新尾指针

}

void delete_project(project* p_last) { // 删除 p_last 的下一个节点 p_cur

    project* p_cur = p_last->next;

    if (p_cur == NULL) return;

    p_last->next = p_cur->next;

    free(p_cur);

}

void read_medal(student* p) {  //文件 读取 medal 结构体

    if (p->pH_medal != NULL) return;

    char fname[40];

    strcpy(fname, "data\\medal\\");

    strcat(fname, p->id);

    strcat(fname, ".txt");

    FILE* fp;

    fp = fopen(fname, "r"); //只读方式打开文件

    p->pH_medal = (medal*)malloc(sizeof(medal)); //初始化头尾指针

    p->pT_medal = p->pH_medal;

    if (fp == NULL) { //如果文件为空，初始化一个无意义的结构体节点

        strcpy(p->pT_medal->name, "奖项");

    }

    else {

        // 读入无效值

        rec_tmp = fscanf(fp, "%s\n", (p->pT_medal)->name);

        // 读入无效值结束

        while (!feof(fp)) { //建表

            medal* pT_next;

            pT_next = (medal*)malloc(sizeof(medal));

            (p->pT_medal)->next = pT_next;

            p->pT_medal = pT_next;

            // 读入文件中一个奖项的所有信息

            rec_tmp = fscanf(fp, "%s ", (p->pT_medal)->node);

            rec_tmp = fscanf(fp, "%s ", (p->pT_medal)->name);

            for (int i = 0; i < 20; i++) {

                rec_tmp = fscanf(fp, "%s ", (p->pT_medal)->member[i]);

            }

            rec_tmp = fscanf(fp, "%s ", (p->pT_medal)->organizer); // 读入无效值

            rec_tmp = fscanf(fp, "%d %d %d %f \n", &((p->pT_medal)->date).year, &((p->pT_medal)->date).month, &((p->pT_medal)->date).day, &(p->pT_medal)->level);

            // 读入结束

        }

        fclose(fp); //建好结构体后直接关闭文件

    }

    (p->pT_medal)->next = NULL; // 结构体末尾指向空

}

void write_medal(student* p) { // medal 结构体 写入 文件

    if (p->pH_medal != NULL) { // 避免对空的头节点进行释放

        char fname[40];

        strcpy(fname, "data\\medal\\");

        strcat(fname, p->id);

        strcat(fname, ".txt");

        FILE* fp;

        fp = fopen(fname, "w"); //只写（删除原内容）

        medal* p_next = (p->pH_medal)->next; //标注已写入数据的空间方便释放

        fprintf(fp, "奖项\n");

        free(p->pH_medal);

        while (p_next != NULL) {

            //  写入文件中一个奖项的所有信息

            fprintf(fp, "%s ", p_next->node);

            fprintf(fp, "%s ", p_next->name);

            for (int i = 0; i < 20; i++) {

                fprintf(fp, "%s ", p_next->member[i]);

            }

            fprintf(fp, "%s ", p_next->organizer); 

            fprintf(fp, "%d %d %d %f \n", (p_next->date).year, (p_next->date).month, (p_next->date).day, p_next->level);

            // 写入结束

            medal* p_free = p_next; // 释放相应空间 

            p_next = p_next->next; //指向下一个位置

            free(p_free);

        }

        fclose(fp);

        p->pH_medal = NULL;

        p->pT_medal = NULL;

    }

}

void create_medal(student* p) { // 在末尾新建一个已经初始化的medal节点

    medal* tmp;

    tmp = (medal*)malloc(sizeof(medal));

    // 初始化开始

    strcpy(tmp->node, "null");

    strcpy(tmp->name, "null");

    for (int i = 0; i < 20; i++) { strcpy(tmp->member[i], "null"); }

    strcpy(tmp->organizer, "null");

    input_time(&(tmp->date), -2, -2, -2);

    tmp->level = 0;

    tmp->next = NULL;

    // 初始化结束

    (p->pT_medal)->next = tmp;

    p->pT_medal = tmp; // 更新尾指针

}

void delete_medal(medal* p_last) { // 删除 p_last 的下一个节点 p_cur

    medal* p_cur;

    p_cur = p_last->next;

    if (p_cur == NULL) return;

    p_last->next = p_cur->next;

    free(p_cur);

}

void read_paper(student* p) {  //文件 读取 paper 结构体

    if (p->pH_paper != NULL) return;

    char fname[40];

    strcpy(fname, "data\\paper\\");

    strcat(fname, p->id);

    strcat(fname, ".txt");

    FILE* fp;

    fp = fopen(fname, "r"); //只读方式打开文件

    p->pH_paper = (paper*)malloc(sizeof(paper));  //初始化头尾指针

    p->pT_paper = p->pH_paper;

    if (fp == NULL) { //如果文件为空，新建一个头节点

        strcpy(p->pT_paper->name, "论文");

    }

    else {

        // 读入无效值

        rec_tmp = fscanf(fp, "%s\n", (p->pT_paper)->name);

        // 读入无效值结束

        while (!feof(fp)) { //建表

            paper* pT_next;

            pT_next = (paper*)malloc(sizeof(paper));

            (p->pT_paper)->next = pT_next;

            p->pT_paper = pT_next;

            // 读入文件中一个论文的所有信息

            rec_tmp = fscanf(fp, "%s %s ", (p->pT_paper)->node, (p->pT_paper)->name);

            for (int i = 0; i < 20; i++) {

                rec_tmp = fscanf(fp, "%s ", (p->pT_paper)->member[i]);

            }

            rec_tmp = fscanf(fp, "%d %d %d %f \n", &((p->pT_paper)->date).year, &((p->pT_paper)->date).month, &((p->pT_paper)->date).day, &(p->pT_paper)->level);

            // 读入结束

        }

        fclose(fp); //建好结构体后直接关闭文件

    }

    (p->pT_paper)->next = NULL; // 结构体末尾指向空

}

void write_paper(student* p) { // paper 结构体 写入 文件

    if (p->pH_paper != NULL) { // 避免对空的头节点进行释放

        char fname[40];

        strcpy(fname, "data\\paper\\");

        strcat(fname, p->id);

        strcat(fname, ".txt");

        FILE* fp;

        fp = fopen(fname, "w"); //只写（删除原内容）

        paper* p_next = (p->pH_paper)->next; //标注已写入数据的空间方便释放

        fprintf(fp, "论文\n");

        free(p->pH_paper);

        while (p_next != NULL) {

            //  写入文件中一个论文的所有信息

            fprintf(fp, "%s %s ", p_next->node , p_next->name);

            for (int i = 0; i < 20; i++) {

                fprintf(fp, "%s ", p_next->member[i]);

            }

            fprintf(fp, "%d %d %d %f \n", (p_next->date).year, (p_next->date).month, (p_next->date).day, p_next->level);

            // 读入结束

            paper* p_free = p_next;; // 释放相应空间 

            p_next = p_next->next; //指向下一个位置

            free(p_free);

        }

        fclose(fp);

        p->pH_paper = NULL;

        p->pT_paper = NULL;

    }

}

void create_paper(student* p) { // 在末尾新建一个已经初始化的paper节点

    paper* tmp;

    tmp = (paper*)malloc(sizeof(paper));

    // 初始化开始

    strcpy(tmp->name, "null");

    for (int i = 0; i < 20; i++) { strcpy(tmp->member[i], "null"); }

    strcpy(tmp->node, "null");

    input_time(&(tmp->date), -2, -2, -2);

    tmp->level = 0;

    tmp->next = NULL;

    // 初始化结束

    (p->pT_paper)->next = tmp;

    p->pT_paper = tmp; // 更新尾指针

}

void delete_paper(paper* p_last) { // 删除 p_last 的下一个节点 p_cur

    paper* p_cur;

    p_cur = p_last->next;

    if (p_cur == NULL) return;

    p_last->next = p_cur->next;

    free(p_cur);

}